/* $Id: communicate.h jjs $ */
/*
   Copyright (C) 2007 by Jurjen Stellingwerff <jurjen@stwerff.xs4all.nl>
   Part of the Moros Project http://moros.sourceforge.net/

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/
#ifndef COMMUNICATE_H_
#define COMMUNICATE_H_

#include "channel.h"
#include <gnutls/gnutls.h>
#include <gnutls/extra.h>

extern void set_blocking(int fileno, bool blocking);
extern bool is_nonblocking_error (void);

/// Class that handles sockets

class communicate {
  private:
	/// List of all current running connections
	list<channel> conns_;
	/// Server socket descriptor
	int serv_socket_;
	/// Server type normal=1 or tls=2
	int type;
	/// Server handler for new client requests
	sigc::signal<void, channel*> serv_handler;
	/// Id for the channels
	int channelnr;
	/// gnutls credentials
	gnutls_certificate_credentials_t cred;
	gnutls_dh_params_t dh_params;
	gnutls_rsa_params_t rsa_params;
	std::string data_dir;
	bool init;

  public:
	communicate();

	/// Free session data
	~communicate();

    void set_dir(std::string dir);
	/// user id for connection
	std::string user;
	/// Session id
	std::string session;
	/// Session nr
	long sessnr;

	/// Read a new data file
	/**
	  \return Returns 0 on failure to connect.
	*/
	channel* reading(const std::string file, sigc::signal<void, channel*> handler);

	/// Write to a file
	/**
	  \return Returns 0 on failure to connect.
	*/
	channel* writing(const std::string file);

	/// Read data from a specified connection
	/**
	  \return Returns 0 on failure to connect.
	*/
	channel* client(const std::string host, int port, sigc::signal<void, channel*> handler);

	/// Reconnect a client
	/**
	  \return if connection is a success
	*/
	bool reconnect(channel* ch);

	/// Listen to this specific socket for requests
	void server(int port, sigc::signal<void, channel*> handler);


	#ifndef no_gnutls
	/// Connect to a tls connection
	/**
	  \return Returns 0 on failure to connect.
	*/
	channel* tls_client(const std::string host, int port, sigc::signal<void, channel*> handler);

	/// Listen with a tls sever for tls clients to connect
	void tls_server(int port, sigc::signal<void, channel*> handler);

	/// Read the dhfile and rsafile into the tls structures
	void tls_reload();
	#endif

	/// read and write data, including cleanup after closed connections or timeouts
	void poll();

	/// open communication till the connection is closed or the timeout is reached
	void complete(int timeout);

	/// Indicate a shutdown of the server
	void server_close();
};

#endif
